package com.coin.websocket;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.coin.exchange.okcoin.websocket.WebSocketService;
import com.coin.exchange.okcoin.websocket.test.WebSoketClient;

@ServerEndpoint("/websocket/okcoin")
@Component
public class OkcoinWebSocket {

	private static Map<String, List<Session>> map = new ConcurrentHashMap<>();
	
	private WebSoketClient okcoinClient;

	@Value("${okcoin.wss.url}")
	private String wss_url = "wss://real.okcoin.com:10440/websocket";

	@OnOpen
	public void onOpen(Session session) {
		System.out.println("有新连接加入！");
	}
	
	@OnClose
	public void onClose() {
		System.out.println("有一连接关闭！");
	}
	
	@OnMessage
	public void onMessage(String message, Session session) {
		JSONObject wsResponse = new JSONObject();
		JSONObject wsRequest = JSONObject.parseObject(message);
		String event = wsRequest.getString("event");
		if ("ping".equals(event)) {
			wsResponse.put("event", "pong");
		} else if ("addChannel".equals(event)) {
			this.addChannel(session, wsRequest.getString("channel"));
			wsResponse.put("channel", wsRequest.getString("channel"));
		}
		this.sendText(session, wsResponse.toJSONString());
	}
	
	@OnError
	public void onError(Session session, Throwable error) {
		error.printStackTrace();
	}
	
	private void addChannel(Session session, String channel) {
		if (okcoinClient == null) {
			okcoinClient = new WebSoketClient(wss_url, new WebSocketService() {
				
				@Override
				public void onReceive(String msg) {
					System.out.println(msg);
					if (msg.startsWith("[")) {
						JSONArray jsonArr = JSONArray.parseArray(msg);
						
						JSONObject jsonObj = jsonArr.getJSONObject(0);
						String channel = jsonObj.getString("channel");
						if (!map.isEmpty() && map.containsKey(channel)) {
							List<Session> list = map.get(channel);
							if (list != null && !list.isEmpty()) {
								for (Session session : list) {
									synchronized (session) {
										try {
											session.getBasicRemote().sendText(msg);
										} catch (Exception e) {
											System.err.println(e.getMessage());
											list.remove(session);
										}
									}
								}
							}
						}
					}
				}
			});
			okcoinClient.start();
		}

		List<Session> list;
		if (map.containsKey(channel)) {
			list = map.get(channel);
		} else {
			list = new ArrayList<>();
			map.put(channel, list);
			okcoinClient.addChannel(channel);
		}
		if (!list.contains(session)) {
			list.add(session);
		}
	}
	
	private void sendText(Session session, String text) {
		try {
			session.getBasicRemote().sendText(text);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}
